<!DOCTYPE html>
<body>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="../forms/resources/common.js"></script>
<div id="log"></div>
<div id="container"></div>
<script>
if (!window.eventSender)
    document.body.textContent = 'This test requires window.eventSender.';

test(function() {
    var container = document.querySelector('#container');
    container.innerHTML = '<input id=prev><div style="height:200px;"><span>text</span></div><input id=next>';
    hoverOverElement(container.querySelector('span'));
    eventSender.mouseDown();
    eventSender.keyDown('\t');
    assert_equals(document.activeElement.id, 'next');
    eventSender.mouseUp();

    hoverOverElement(container.querySelector('div'));
    eventSender.mouseDown();
    eventSender.keyDown('\t', ['shiftKey']);
    assert_equals(document.activeElement.id, 'prev');
    eventSender.mouseUp();

    container.innerHTML = '<span style="font-size:60px;"><input id=prev>Text Text<input id=next></span>';
    hoverOverElement(container.querySelector('span'));
    eventSender.mouseDown();
    eventSender.keyDown('\t');
    assert_equals(document.activeElement.id, 'next');
    eventSender.mouseUp();

    hoverOverElement(container.querySelector('span'));
    eventSender.mouseDown();
    eventSender.keyDown('\t', ['shiftKey']);
    assert_equals(document.activeElement.id, 'prev');
    eventSender.mouseUp();
}, 'Mouse press should update sequential focus navigation starting point.');

test(function() {
    var container = document.querySelector('#container');
    container.innerHTML = '<a href="#fragment"></a><input id=prev><a name="fragment"></a><input id=next>';
    container.querySelector('a').click();
    eventSender.keyDown('\t');
    assert_equals(document.activeElement.id, 'next');
}, 'Fragment navigation should update sequential focus navigation starting point.');

test(function() {
    var container = document.querySelector('#container');
    container.innerHTML = '<input id=prev><input id=start><input id=next>';
    container.querySelector('#start').focus();
    container.querySelector('#start').blur();
    eventSender.keyDown('\t');
    assert_equals(document.activeElement.id, 'next');
}, 'Focusing an element should update sequential focus navigation starting point.');

test(function() {
    var container = document.querySelector('#container');
    container.innerHTML = '<input id=prev><input id=start><input id=next>';
    container.querySelector('#start').focus();
    container.querySelector('#start').remove();
    eventSender.keyDown('\t');
    assert_equals(document.activeElement.id, 'next');

    container.innerHTML = '<input id=prev><input id=start><input id=next>';
    container.querySelector('#start').focus();
    container.querySelector('#start').remove();
    eventSender.keyDown('\t', ['shiftKey']);
    assert_equals(document.activeElement.id, 'prev');
}, 'After removing a focused element from the documen tree, sequential focus navigation should start at a place where the focused element was.');

test(function() {
    const container = document.querySelector('#container');
    container.innerHTML = '<input id="before"><div></div><input id="after">';
    const host = container.querySelector('div');
    const shadowRoot = host.attachShadow({mode:'closed'});

    let buttonInShadow = document.createElement('button');
    shadowRoot.appendChild(buttonInShadow);
    buttonInShadow.focus();
    assert_equals(shadowRoot.activeElement, buttonInShadow);
    buttonInShadow.remove();
    eventSender.keyDown('\t');
    assert_equals(document.activeElement.id, 'after', 'Forward');

    buttonInShadow = document.createElement('button');
    shadowRoot.appendChild(buttonInShadow);
    buttonInShadow.focus();
    assert_equals(shadowRoot.activeElement, buttonInShadow);
    buttonInShadow.remove();
    eventSender.keyDown('\t', ['shiftKey']);
    assert_equals(document.activeElement.id, 'before', 'Backward');
}, 'Disconnecting a focused element in a shadow tree');

test(function() {
    const container = document.querySelector('#container');
    container.innerHTML = '<input id="before"><div></div><input id="after">';

    let host = container.querySelector('div');
    let shadowRoot = host.attachShadow({mode:'closed'});
    let buttonInShadow = document.createElement('button');
    shadowRoot.appendChild(buttonInShadow);
    buttonInShadow.focus();
    assert_equals(shadowRoot.activeElement, buttonInShadow);
    host.remove();
    eventSender.keyDown('\t');
    assert_equals(document.activeElement.id, 'after', 'Forward');

    container.insertBefore(host, container.lastChild);
    buttonInShadow.focus();
    assert_equals(shadowRoot.activeElement, buttonInShadow);
    host.remove();
    eventSender.keyDown('\t', ['shiftKey']);
    assert_equals(document.activeElement.id, 'before', 'Backward');
}, 'Disconnecting a shadow tree including a focused element');

test(function() {
    // crbug.com/897403
    const container = document.querySelector('#container');
    container.innerHTML = '<input id="before"><span><div></div><div></div></span><input id="after">';

    let host = container.querySelector('div');
    let hostParent = host.parentNode;
    let shadowRoot = host.attachShadow({mode:'closed'});
    let buttonInShadow = document.createElement('button');
    shadowRoot.appendChild(buttonInShadow);
    buttonInShadow.focus();
    assert_equals(shadowRoot.activeElement, buttonInShadow);
    hostParent.innerHTML = '';
    eventSender.keyDown('\t');
    assert_equals(document.activeElement.id, 'after', 'Forward');
}, 'Disconnecting a shadow tree including a focused element 2');

test(function() {
    var container = document.querySelector('#container');
    container.innerHTML = '<input id="i1"><input id="i2"><input id="i3">';
    container.querySelector('#i3').click();
    container.querySelector('#i1').scrollIntoView();
    eventSender.keyDown('\t');
    assert_equals(document.activeElement.id, 'i2');
}, 'Element.scrollIntoView() should update sequential focus navigation starting point.');

test(function() {
    var container = document.querySelector('#container');
    container.innerHTML = '<span>Lorem</span><span tabindex="0" id="ipsum">ipsum</span><span>dolor</span><span tabindex="0" id="sit">sit</span><span>amet</span>';
    testRunner.findString("dolor", []);
    eventSender.keyDown('\t');
    assert_equals(document.activeElement.id, 'sit');
    testRunner.findString("Lorem", []);
    eventSender.keyDown('\t');
    assert_equals(document.activeElement.id, 'ipsum');
    testRunner.findString("amet", []);
    eventSender.keyDown('\t', ['shiftKey']);
    assert_equals(document.activeElement.id, 'sit');
}, 'Find text should update sequential focus navigation starting point.');

var t = async_test('Cross-frame sequential focus navigation should clear per-document starting point.');
t.step(() => {
    var container = document.querySelector('#container');
    container.innerHTML = '<iframe tabindex=0 srcdoc="<input id=inner1><input id=inner2>"></iframe><input id=outer1>';
    var iframe = container.firstChild;
    document.querySelector('#outer1').addEventListener('focus', () => { iframe.focus() }, false);
    iframe.addEventListener('load', t.step_func(() => {
        var inner2 = iframe.contentDocument.querySelector('#inner2');
        inner2.focus();
        eventSender.keyDown('\t');
        eventSender.keyDown('\t', ['shiftKey']);
        assert_equals(iframe.contentDocument.activeElement, inner2);
        t.done();
    }), false);
});
</script>
</body>
